﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;

namespace TeBigCommonUI.Common
{
    public class LayoutHelper : IMultiValueConverter
    {
        private static LayoutHelper Instance = new LayoutHelper();

        #region ParentElement
        public static FrameworkElement GetParentElement(DependencyObject obj)
        {
            return (FrameworkElement)obj.GetValue(ParentElementProperty);
        }

        public static void SetParentElement(DependencyObject obj, FrameworkElement value)
        {
            obj.SetValue(ParentElementProperty, value);
        }

        // Using a DependencyProperty as the backing store for ParentElement.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ParentElementProperty =
            DependencyProperty.RegisterAttached("ParentElement", typeof(FrameworkElement), typeof(LayoutHelper),
                new PropertyMetadata(null));


        #endregion



        #region WidthPercent
        public static double GetWidthPercent(DependencyObject obj)
        {
            return (double)obj.GetValue(WidthPercentProperty);
        }

        public static void SetWidthPercent(DependencyObject obj, double value)
        {
            obj.SetValue(WidthPercentProperty, value);
        }

        public static readonly DependencyProperty WidthPercentProperty =
            DependencyProperty.RegisterAttached("WidthPercent", typeof(double),
                typeof(LayoutHelper), new PropertyMetadata(100d, WidthPercentChanged));


        public static void WidthPercentChanged(
            DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (!(obj is FrameworkElement ui) || (double)e.NewValue < 0)
                return;

            var binding = new MultiBinding
            {
                Converter = Instance,
                ConverterParameter = ParameterKind.Width,
            };

            var parent = GetParentElement(obj) ?? ui.Parent;

            binding.Bindings.Add(new Binding() { Source = parent, Path = new PropertyPath(FrameworkElement.ActualWidthProperty) });
            binding.Bindings.Add(new Binding() { Source = obj, Path = new PropertyPath(WidthPercentProperty) });


            BindingOperations.SetBinding(obj, FrameworkElement.WidthProperty, binding);
        }

        #endregion

        #region HeightPercent


        public static double GetHeightPercent(DependencyObject obj)
        {
            return (double)obj.GetValue(HeightPercentProperty);
        }

        public static void SetHeightPercent(DependencyObject obj, double value)
        {
            obj.SetValue(HeightPercentProperty, value);
        }

        // Using a DependencyProperty as the backing store for HeightPercent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HeightPercentProperty =
            DependencyProperty.RegisterAttached("HeightPercent", typeof(double), typeof(LayoutHelper), 
                new PropertyMetadata(100d, HeightPercentChanged));

        public static void HeightPercentChanged(
            DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            if (!(obj is FrameworkElement ui) || (double)e.NewValue < 0)
                return;

            var binding = new MultiBinding
            {
                Converter = Instance,
                ConverterParameter = ParameterKind.Height,
            };

            var parent = GetParentElement(obj) ?? ui.Parent;

            binding.Bindings.Add(new Binding() { Source = parent, Path = new PropertyPath(FrameworkElement.ActualWidthProperty) });
            binding.Bindings.Add(new Binding() { Source = obj, Path = new PropertyPath(HeightPercentProperty) });


            BindingOperations.SetBinding(obj, FrameworkElement.HeightProperty, binding);
        }
        #endregion


        #region IValueConverter

        enum ParameterKind
        {
            Width = 0,
            Height,
        }

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (parameter is ParameterKind pk)
            {
                if (pk == ParameterKind.Width && values[0] is double actual_w && values[1] is double percent_w)
                    return actual_w * (percent_w * 0.01);

                if (pk == ParameterKind.Height && values[0] is double actual_h && values[1] is double percent_h)
                    return actual_h * (percent_h * 0.01);
            }

            return null;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        #endregion


    }
}
